package hot100;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class Solution399 {
    public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
        int size = equations.size();
        UnionFind unionFind = new UnionFind(2 * size);
        HashMap<String, Integer> map = new HashMap<>();
        int index = 0;
        for (int i = 0; i < equations.size(); i++) {
            String var1 = equations.get(i).get(0);
            String var2 = equations.get(i).get(1);
            if (map.get(var1) == null) {
                map.put(var1, index);
                index++;
            }
            if (map.get(var2) == null) {
                map.put(var2, index);
                index++;
            }
            unionFind.union(map.get(var1), map.get(var2), values[i]);
        }
        double[] ans = new double[queries.size()];
        for (int i = 0; i < ans.length; i++) {
            String var1 = queries.get(i).get(0);
            String var2 = queries.get(i).get(1);
            if (map.get(var1) != null && map.get(var2) != null) {
                ans[i] = unionFind.getWeight(map.get(var1), map.get(var2));
            } else {
                ans[i] = -1.0;
            }
        }
        return ans;

    }

    class UnionFind {
        private int[] parent;
        private double[] weight;

        public UnionFind(int n) {
            parent = new int[n];
            weight = new double[n];
            for (int i = 0; i < n; i++) {
                parent[i] = i;
                weight[i] = 1.0;
            }
        }

        public int find(int x) {
            while(parent[x] != x) {
                int origin = parent[x];
                parent[x] = find(parent[x]);
                weight[x] *= weight[origin];
            }
            return parent[x];
        }

        public void union(int x, int y, double value) {
            int rootX = find(x);
            int rootY = find(y);
            if (rootX == rootY) {
                return;
            }
            parent[rootX] = rootX;
            weight[rootX] = weight[y] * value / weight[x];
        }

        public double getWeight(int x, int y) {
            int rootX = find(x);
            int rootY = find(y);
            if (rootX == rootY) {
                return weight[x] / weight[y];
            } else {
                return -1.0;
            }
        }
    }


    public static void main(String[] args) {
        Solution399 solution399 = new Solution399();
        List<List<String>> equations = new LinkedList<>();
        List<String> equa1 = new LinkedList<>();
        equa1.add("a");
        equa1.add("b");
        equations.add(equa1);
        equa1 = new LinkedList<>();
        equa1.add("b");
        equa1.add("c");
        equations.add(equa1);
        double[] value = new double[] {2.0, 3.0};
        List<List<String>> queries = new LinkedList<>();
        List<String> query = new LinkedList<>();
        query.add("a");
        query.add("c");
        queries.add(query);
        query = new LinkedList<>();
        query.add("b");
        query.add("a");
        queries.add(query);
        query = new LinkedList<>();
        query.add("a");
        query.add("e");
        queries.add(query);
        query = new LinkedList<>();
        query.add("a");
        query.add("a");
        queries.add(query);
        query.add("x");
        query.add("x");
        queries.add(query);
        solution399.calcEquation(equations, value, queries);

    }
}
